package com.heima.media.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.dto.ResponseResult;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.minio.MinIOService;
import com.heima.common.util.SensitiveWordUtil;
import com.heima.media.dto.ArticleDto;
import com.heima.media.dto.ContentDto;
import com.heima.media.dto.ImageDto;
import com.heima.media.entity.WmChannel;
import com.heima.media.entity.WmNews;
import com.heima.media.entity.WmSensitive;
import com.heima.media.entity.WmUser;
import com.heima.media.feign.ArticleClient;
import com.heima.media.service.*;
import org.apache.commons.io.IOUtils;
import org.checkerframework.checker.units.qual.A;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.InputStream;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;


@Service
public class AuditServiceImpl implements IAuditService {
    @Async  // 当前方法需要使用线程来执行
    @Override
    public void audit(WmNews wmNews) {
        System.out.println(Thread.currentThread().getName() + " 开始执行审核...newsId = " + wmNews.getId());
        // 判断当前文章的状态  0 草稿  1 提交（待审核） 2 审核失败 3 人工审核  4 人工审核通过  8 审核通过（待发布） 9 已发布


        // 如果状态是8或者4  开始进入文章发布
        if (wmNews.getStatus() == 8 || wmNews.getStatus() == 4) {
            // 判断是否到了发布时间
            if (wmNews.getPublishTime().getTime() > System.currentTimeMillis()) {
                sendDelayMessage(wmNews);
            } else {
                publishArticle(wmNews);
            }
            return;
        }

        // 如果状态是1 进入自动审核流程

        // 提取内容中文本和图片
        Map<String, Object> map = getTextAndImageFromContent(wmNews.getContent());
        // 获取文本内容
        String text = (String) map.get("text");
        // 获取图片内容
        List<String> image = (List<String>) map.get("image");

        // 自管理敏感词审核
        boolean selfResult = checkSelf(wmNews, text);
        if (!selfResult) return;

        // 调用阿里云文本审核
        boolean textResult = checkText(wmNews, text);
        if (!textResult) return;

        // 调用阿里云图片审核
        boolean imageResult = checkImage(wmNews, image);
        if (!imageResult) return;
        // 调用文章服务接口保存文章

        // 判断如果还没有到发布时间,将文章状态改为 8 审核通过（待发布） 发送延迟任务(消息)
        if (wmNews.getPublishTime().getTime() > System.currentTimeMillis()) {
            wmNews.setStatus(8);
            newsService.updateById(wmNews);
            sendDelayMessage(wmNews);
        } else {
            publishArticle(wmNews);
        }
        System.out.println(Thread.currentThread().getName() + " 执行审核完成.");
    }

    private boolean checkSelf(WmNews wmNews, String text) {
        return false;
    }

    /**
     * 发送延迟消息
     *
     * @param wmNews
     */
    private void sendDelayMessage(WmNews wmNews) {
        wmNews.setStatus(8);
        newsService.updateById(wmNews);
        // 发送延迟消息,将发布时间到当前时间的差作为延迟间隔
        // 创建一个延迟队列
        RQueue<String> rQueue = redissonClient.getBlockingQueue("article-publish");
        RDelayedQueue<String> delayedQueue = redissonClient.getDelayedQueue(rQueue);
        // 发送延迟消息
        long time = wmNews.getPublishTime().getTime() - System.currentTimeMillis();
        delayedQueue.offer(JSON.toJSONString(wmNews), time, TimeUnit.MILLISECONDS);
    }

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private IWmSensitiveService sensitiveService;

    /**
     * 自管理敏感词的审核
     *
     * @param wmNews
     * @param text
     * @return
     */
    private boolean checkWordNew(WmNews wmNews, String text) {
        boolean result = true;
        String content = wmNews.getTitle() + wmNews.getLabels() + text;
        // 判断数据结构中是否已经存在数据
        if (SensitiveWordUtil.dictionaryMap.size() <= 0) {
            // 查询数据库中所有的敏感词
            LambdaQueryWrapper<WmSensitive> query = new LambdaQueryWrapper<>();
            // select sensitives from wm_sensitive;
            query.select(WmSensitive::getSensitives);
            List<String> words = sensitiveService.listObjs(query, o -> o.toString());
            // 初始化
            SensitiveWordUtil.initMap(words);
        }
        // 校验内容
        Map<String, Integer> map = SensitiveWordUtil.matchWords(content);
        if (map.size() > 0) {
            result = false;
            wmNews.setStatus(2);
            Set<String> keySet = map.keySet();
            String join = String.join(",", keySet);
            wmNews.setReason("自管理敏感词审核失败: " + join);
            newsService.updateById(wmNews);
        }
        return result;
    }

    /**
     * 自管理敏感词的审核
     *
     * @param wmNews
     * @param text
     * @return
     */
    private boolean checkWord(WmNews wmNews, String text) {
        boolean result = true;
        String content = wmNews.getTitle() + wmNews.getLabels() + text;
        // 查询数据库中所有的敏感词
        List<WmSensitive> words = sensitiveService.list();
        // 遍历敏感词,判断敏感词是否出现在 text 中
        for (WmSensitive word : words) {
            if (content.contains(word.getSensitives())) {
                result = false;
                wmNews.setStatus(2);
                wmNews.setReason("自管理敏感词审核失败: " + word.getSensitives());
                newsService.updateById(wmNews);
                break;
            }
        }
        return result;
    }

    @Autowired
    private ArticleClient articleClient;

    @Autowired
    private IWmUserService userService;

    @Autowired
    private IWmChannelService channelService;

    /**
     * 发布文章到文章库
     *
     * @param wmNews
     */
    private void publishArticle(WmNews wmNews) {
        ArticleDto dto = new ArticleDto();
        // 构建文章属性
        BeanUtils.copyProperties(wmNews, dto);
        dto.setId(wmNews.getArticleId());
        // 从自媒体用户表中查询作者信息
        WmUser user = userService.getById(wmNews.getUserId());
        dto.setAuthorId(user.getApAuthorId());
        dto.setAuthorName(user.getName());
        // 查询频道信息
        WmChannel channel = channelService.getById(wmNews.getChannelId());
        dto.setChannelName(channel.getName());
        dto.setLayout(wmNews.getType());
        dto.setFlag(0);
        // 前端显示的图片是根据逗号分隔的,格式: 1.jpg,2.jpg,3.jpg
        // 自媒体中的封面图片是  List<ImageDto> 的json格式
        List<String> images = new ArrayList<>();
        List<ImageDto> list = JSON.parseArray(wmNews.getImages(), ImageDto.class);
        for (ImageDto imageDto : list) {
            images.add(imageDto.getUrl());
        }
        // 将List<String> images 转换成逗号分隔的字符串
        String imageStr = String.join(",", images);
        dto.setImages(imageStr);
        dto.setLikes(0);
        dto.setComment(0);
        dto.setCollection(0);
        dto.setViews(0);
        dto.setSyncStatus(0);

        ResponseResult<Long> responseResult = articleClient.saveArticle(dto);
        if (responseResult.getCode().equals(AppHttpCodeEnum.SUCCESS.getCode())) {
            // 获取到生产的文章id
            Long articleId = responseResult.getData();
            if (articleId != null) {
                // 修改自媒体文章状态为9 ,将文章id记录到表中
                wmNews.setStatus(9);
                wmNews.setArticleId(articleId);
                newsService.updateById(wmNews);
            }
        }
    }

    @Autowired(required = false)
    private GreenImageScan imageScan;

    @Autowired
    private MinIOService minIOService;

    /**
     * 阿里云进行图片审核
     *
     * @param wmNews
     * @param images
     * @return
     */
    private boolean checkImage(WmNews wmNews, List<String> images) {
        if (images.size() <= 0) {
            return true;
        }
        boolean result = false;
        List<byte[]> imageList = new ArrayList<>();
        try {
            // 遍历图片地址
            for (String image : images) {
                // 从minio下载图片
                InputStream inputStream = minIOService.download(image);
                // 将输入流转换成字节数组
                byte[] array = IOUtils.toByteArray(inputStream);
                // 将这张图片的字节数组加入到上面的集合中
                imageList.add(array);
            }
            Map map = imageScan.imageScan(imageList);
            if (map != null) {
                // 分析阿里云返回的结果
                String suggestion = (String) map.get("suggestion");
                switch (suggestion) {
                    case "pass":
                        result = true;
                        break;
                    case "block":
                        // 审核不通过,修改自媒体文章状态为 2
                        wmNews.setStatus(2);
                        // 记录失败的原因
                        String label = (String) map.get("label");
                        wmNews.setReason("阿里云图片审核失败..." + label);
                        // 更新数据库
                        newsService.updateById(wmNews);
                        break;
                    case "review":
                        // 修改自媒体文章状态为 3,进入人工审核流程
                        wmNews.setStatus(3);
                        newsService.updateById(wmNews);
                        break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    @Autowired(required = false)
    private GreenTextScan textScan;

    @Autowired
    private IWmNewsService newsService;

    /**
     * 阿里云进行文本内容审核
     *
     * @param wmNews
     * @param text
     * @return
     */
    private boolean checkText(WmNews wmNews, String text) {
        boolean result = false;
        //审核内容包含: 标题+标签+正文中的文字内容(不包含图片链接)
        String content = wmNews.getTitle() + wmNews.getLabels() + text;
        try {
            Map map = textScan.greenTextScan(content);
            // 分析阿里云返回的结果
            String suggestion = (String) map.get("suggestion");
            switch (suggestion) {
                case "pass":
                    result = true;
                    break;
                case "block":
                    // 审核不通过,修改自媒体文章状态为 2
                    wmNews.setStatus(2);
                    // 记录失败的原因
                    String label = (String) map.get("label");
                    wmNews.setReason("阿里云文本审核失败..." + label);
                    // 更新数据库
                    newsService.updateById(wmNews);
                    break;
                case "review":
                    // 修改自媒体文章状态为 3,进入人工审核流程
                    wmNews.setStatus(3);
                    newsService.updateById(wmNews);
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 提取内容中的文字和图片
     *
     * @param content
     * @return
     */
    private Map<String, Object> getTextAndImageFromContent(String content) {
        Map<String, Object> map = new HashMap<>();
        // 将所有文字提取出来,拼接在一起
        StringBuilder stringBuilder = new StringBuilder();
        // 定义图片的url地址集合
        List<String> list = new ArrayList<>();
        // 将json转换成对象集合
        List<ContentDto> dtos = JSON.parseArray(content, ContentDto.class);
        for (ContentDto dto : dtos) {
            if (dto.getType().equals("text")) {
                stringBuilder.append(dto.getValue());
            } else {
                list.add(dto.getValue());
            }
        }
        map.put("text", stringBuilder.toString());
        map.put("image", list);
        return map;
    }
}
